#include "m_predis.h"
#include "agent.h"
#include "segment.h"
#include "span.h"
#include "helper.h"
// #include "skywalking_client.h"

#include <string>

void monitorpro_predis_handler(zend_execute_data *execute_data, long start_micro_time, long end_micro_time, std::string class_name, std::string function_name)
{
    uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data);
    if (arg_count)
    {
        // 初始化参数
        std::string operate = "";
        std::string key = "";
        std::string ip = "";
        std::string port = "";
        std::string addr = "";
        std::string err = "";
        std::string query = "";

        zval *connection = read_obj_property(&(execute_data->This), "connection", "Predis\\Connection\\StreamConnection");
        if (connection == nullptr)
        {
            return;
        }
        zval *parameters = read_obj_property(connection, "parameters", "Predis\\Connection\\Parameters");
        if (parameters == nullptr)
        {
            return;
        }
        zval *params = read_property(parameters, "parameters");
        zval *z_host = zend_hash_str_find(Z_ARRVAL_P(params), "host", sizeof("host") - 1);
        zval *z_port = zend_hash_str_find(Z_ARRVAL_P(params), "port", sizeof("port") - 1);
        zval z_port_o;
        ZVAL_COPY(&z_port_o, z_port);
        ip = ZSTR_VAL(Z_STR_P(z_host));
        convert_to_long(&z_port_o);
        port = std::to_string(Z_LVAL(z_port_o));
        addr = ip + ":" + port;

        // 获取函数传参
        uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data);
        if (arg_count)
        {
            zval *id = ZEND_CALL_ARG(execute_data, 1);
            if (Z_TYPE_P(id) == IS_STRING)
            {
                operate = Z_STRVAL_P(id);
            }
        }

        query = class_name + "->" + function_name + "::" + operate;

        // SkywalkingClient *skywalking_client = SkywalkingClient::newInstance();
        // Segment *segment = skywalking_client->getSegment();
        // auto *span = segment->createSpan(SkySpanType::Exit, SkySpanLayer::Database, 8003);
        // span->setOperationName(class_name + "->" + function_name);
        // span->addTag("db.type", "redis");
        // span->addTag("db.driver", "predis");
        // span->addTag("redis.command", operate);
        // span->setPeer(addr);
        // span->setStartTime(start_micro_time / 1000);
        // span->setEndTime(end_micro_time / 1000);

        push_redis_data(addr, query, err, end_micro_time - start_micro_time);
    }
}